// 引入 axios 库
import axios from 'axios'
import { Message } from 'element-ui'
import store from '@/store'
import router from '@/router'

// 创建 axios 实例
const service = axios.create({
  // process.env 是脚手架工具获取环境变量的属性
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 5000 // request timeout
})

const checkTimeout = () => {
  // 之前是判断到有 token 就带上 token
  // 由于需要被动介入, 还要检查超时文成
  const timeout = 1000 * 60 * 60 * 2
  const now = Date.now()
  const loginTime = localStorage.getItem('timestamp')
  return now - loginTime > timeout
}

// 请求拦截器, 给每个接口都带上 token
// 拦截到的形参一般叫 config 当前请求的配置
// 登录接口例外, 其实就是必须登陆过有 token 才能带上
service.interceptors.request.use(config => {
  if (store.getters.token) {
    if (checkTimeout()) {
      // 清理数据, 跳转登录页, 阻止当前请求
      store.dispatch('user/logout')
      router.push('/login')
      return Promise.reject(new Error('登录已超时(主动介入)'))
    }

    config.headers.Authorization = 'Bearer ' + store.getters.token
  }
  return config
})

// 响应拦截器 统一处理错误
// 响应拦截器, 可以接受两个回调, 第一个会拦截到网络成功
// 第二个拦截到的是网络失败
service.interceptors.response.use(res => {
  // 成功返回数据
  if (res.data.success) {
    // 请求成功数据也没问题, 返回最终的结果
    return res.data.data
  } else {
    // 网络请求没问题, 响应 200 但是后端说 数据层面出了问题
    // 提示用户
    Message.error(res.data.message)
    // 阻止当前请求
    // throw new Error(res.data.message)
    return Promise.reject(new Error(res.data.message))
  }
}, err => {
  // 网络请求完全失败, 如写错 url, 或者断网, 或者服务器崩溃
  // 提示用户
  // 阻止当前请求
  console.dir(err)
  // 这里的错误可能性很多, 之前是统一进行处理
  // 现在要处理一种独特情况, 后端告诉我们 token 失效
  // 注意由于错误可能性太多, 比如断网, 服务器崩溃的情况下,
  // 可能连 response 都没有, 为了防止出 undefined 取值的问题
  // 先确认 response 存在再做 token 验证
  if (err.response && err.response.data.code === 10002) {
    store.dispatch('user/logout')
    router.push('/login')
  }

  Message.error(err.message)
  // throw err
  return Promise.reject(err)
})

// 导出实例
export default service
